//
//  HLControl.swift
//  SwiftFoundation
//
//  Created by hulinhu on 2017/11/20.
//  Copyright © 2017年 hulinhu. All rights reserved.
//  正式版

import UIKit
import ObjectiveC

// 1.定义一个闭包类型
//格式: typealias 闭包名称 = (参数名称: 参数类型) -> 返回值类型
typealias sTapAction = () -> Void

class  HLControl : NSObject {
    
    // MARK: -  For UIView
    class  func createUIViewWithFrame(frame :CGRect ,bgColor :UIColor? ) -> UIView {
        let sView  = UIView()
        sView.frame = frame
        if let bgColor = bgColor {
            sView.backgroundColor = bgColor
        }
        return sView
    }
    
    class  func createUIViewWithFrame(frame :CGRect ,bgColor :UIColor ,cornerRadius:CGFloat? ) -> UIView {
        let sView  = createUIViewWithFrame(frame: frame, bgColor: bgColor)
        if cornerRadius! > 0 {
            sView.clipsToBounds = true
            sView.layer.cornerRadius = cornerRadius!
            sView.layer.masksToBounds = true;
        }
        return sView
    }
    
    class  func createUIViewWithFrame(frame :CGRect ,bgColor :UIColor ,cornerRadius:CGFloat ,
                                      actionGesture: UIGestureRecognizer ) -> UIView {
        
        let sView  = createUIViewWithFrame(frame: frame, bgColor: bgColor, cornerRadius:cornerRadius)
        sView.addGestureRecognizer(actionGesture)
        return sView
    }
    
    class func createUIViewWithFrame(frame :CGRect ,bgColor :UIColor ,cornerRadius:CGFloat ,
                                     tapAction:@escaping sTapAction) -> UIView {
        
        let sTap = tapGestureBlock.init(action: { (tapGesture) in
            tapAction()
        })
        let sView  = createUIViewWithFrame(frame: frame, bgColor: bgColor, cornerRadius:cornerRadius ,actionGesture:sTap)
        return sView
    }
    
    // MARK: - For UILabel
    class  func createLabelWithFrame(frame :CGRect ,text :String? ,textAlignment:NSTextAlignment?,
                                     fontSize: CGFloat? ) -> UILabel {
        let sLabel  = UILabel()
        sLabel.frame = frame
        
        if let text = text {
            sLabel.text = text
        }
        
        if let fontSize = fontSize {
            sLabel.font = UIFont.systemFont(ofSize: fontSize)
        }
        return sLabel
    }
    
    class  func createLabelWithFrame(frame :CGRect ,text:String ,textAlignment:NSTextAlignment ,
                                     fontSize: CGFloat,textColor:UIColor? ) -> UILabel {
        let sLabel  = createLabelWithFrame(frame: frame, text: text, textAlignment: textAlignment,
                                           fontSize: fontSize)
        if let textColor = textColor {
            sLabel.textColor = textColor
        }
        return sLabel
    }
    
    class  func createLabelWithFrame(frame :CGRect ,text :String ,textAlignment:NSTextAlignment,
                                     fontSize: CGFloat,textColor:UIColor,bgColor:UIColor? ) -> UILabel {
        let sLabel  = createLabelWithFrame(frame: frame, text: text, textAlignment: textAlignment,
                                           fontSize: fontSize, textColor: textColor )
        
        if let bgColor = bgColor {
            sLabel.backgroundColor = bgColor
        }
        return sLabel
    }
    
    class  func createLabelWithFrame(frame :CGRect ,text :String ,textAlignment:NSTextAlignment,
                                     fontSize: CGFloat,textColor:UIColor ,bgColor:UIColor ,cornerRadius:CGFloat? ) -> UILabel {
        let sLabel  = createLabelWithFrame(frame: frame, text: text, textAlignment: textAlignment,
                                           fontSize: fontSize, textColor: textColor ,bgColor: bgColor)
        if cornerRadius! > 0 {
            sLabel.clipsToBounds = true
            sLabel.layer.cornerRadius = cornerRadius!
            sLabel.layer.masksToBounds = true;
        }
        return sLabel
    }
    
    
    class  func createLabelWithFrame(frame :CGRect ,text :String ,textAlignment:NSTextAlignment,
                                     fontSize: CGFloat,textColor:UIColor ,bgColor:UIColor ,cornerRadius:CGFloat , tapAction:@escaping sTapAction ) -> UILabel {
        
        let sTap = tapGestureBlock.init(action: { (tapGesture) in
            tapAction()
        })
        let sLabel  = createLabelWithFrame(frame: frame, text: text, textAlignment: textAlignment,
                                           fontSize: fontSize, textColor: textColor ,bgColor: bgColor ,cornerRadius:cornerRadius)
        sLabel.isUserInteractionEnabled = true
        sLabel.addGestureRecognizer(sTap)
        return sLabel
    }
    
    
    // MARK: -  For UIImageView
    class  func createImageViewWithFrame(frame :CGRect ,imageName :String? ) -> UIImageView {
        let sImageView  = UIImageView()
        sImageView.frame = frame
        sImageView.contentMode = .scaleAspectFit
        
        if let imageName = imageName {
            sImageView.image = UIImage.init(named: imageName)
        }
        return sImageView
    }
    
    class  func createImageViewWithFrame(frame :CGRect ,imageName :String, cornerRadius:CGFloat? ) -> UIImageView {
        let sImageView  =  createImageViewWithFrame(frame: frame, imageName: imageName)
        if cornerRadius! > 0 {
            sImageView.clipsToBounds = true;
            sImageView.layer.cornerRadius = cornerRadius!;
            sImageView.layer.masksToBounds = true;
        }
        return sImageView
    }
    
    class  func createImageViewWithFrame(frame :CGRect ,imageName :String, cornerRadius:CGFloat ,
                                         actionGesture:UIGestureRecognizer) -> UIImageView {
        let sImageView  =  createImageViewWithFrame(frame: frame, imageName: imageName, cornerRadius:cornerRadius)
        sImageView.isUserInteractionEnabled = true
        sImageView.addGestureRecognizer(actionGesture)
        return sImageView
    }
    
    class  func createImageViewWithFrame(frame :CGRect ,imageName :String, cornerRadius:CGFloat ,
                                         tapAction:@escaping sTapAction) -> UIImageView {
        
        let sTap = tapGestureBlock.init(action: { (tapGesture) in
            tapAction()
        })
        let sImageView  = createImageViewWithFrame(frame: frame, imageName: imageName,
                                                   cornerRadius:cornerRadius, actionGesture:sTap)
        return sImageView
    }
    
    class  func createImageViewWithFrame(frame :CGRect ,imageName :String, roundCorner:Bool ,
                                         tapAction:@escaping sTapAction ) -> UIImageView {
        var cornerRadius : CGFloat = 0
        if roundCorner {
            cornerRadius = frame.size.width/CGFloat(2);
        }
        let sImageView  = createImageViewWithFrame(frame: frame, imageName: imageName, cornerRadius: cornerRadius, tapAction: tapAction)
        
        return sImageView
    }
    
    // MARK: -  For UIButton
    class  func createButtonWithFrame(frame :CGRect, title:String?, fontSize:CGFloat?,
                                      imageName:String?, bgImageName:String?,tapAction:@escaping sTapAction) -> UIButton {
        
        let sButton = UIButton.init(type: .custom)
        sButton.frame = frame
        
        if let title = title {
            sButton.setTitle(title, for: .normal)
        }
        if  let fontSize = fontSize {
            sButton.titleLabel?.font = UIFont.systemFont(ofSize: fontSize)
        }
        
        if  let imageName = imageName {
            sButton.setImage(UIImage.init(named: imageName), for: .normal)
        }
        
        if  let bgImageName = bgImageName  {
            sButton.setBackgroundImage(UIImage.init(named: bgImageName), for: .normal)
        }
        sButton.addBlockForControlEvents(controlEvents: .touchUpInside) { (sender: Any) in
            tapAction()
        }
        return sButton
        
    }
    
    class  func createButtonWithFrame(frame :CGRect, title:String, fontSize:CGFloat,
                                      titleColor:UIColor?, bgColor:UIColor?, imageName:String, bgImageName:String,
                                      tapAction:@escaping sTapAction) -> UIButton{
        
        let sButton = createButtonWithFrame(frame: frame, title: title, fontSize: fontSize, imageName: imageName, bgImageName: bgImageName, tapAction: tapAction)
        
        if  let titleColor = titleColor {
            sButton.setTitleColor(titleColor, for: .normal)
        }
        
        if  let bgColor = bgColor {
            sButton.backgroundColor = bgColor
        }
        return sButton
    }
    
    class  func createButtonWithFrame(frame :CGRect, title:String, fontSize:CGFloat,
                                      titleColor:UIColor, bgColor:UIColor, imageName:String, bgImageName:String, cornerRadius:CGFloat?,
                                      tapAction:@escaping sTapAction) -> UIButton{
        
        let sButton = createButtonWithFrame(frame: frame, title: title, fontSize: fontSize, titleColor: titleColor, bgColor: bgColor, imageName: imageName, bgImageName: bgImageName, tapAction: tapAction)
        if cornerRadius! > 0 {
            sButton.clipsToBounds = true;
            sButton.layer.cornerRadius = cornerRadius!;
            sButton.layer.masksToBounds = true;
        }
        
        return sButton
    }
    
    // MARK: - For UITextField
    class  func createTextFiledWithFrame(frame :CGRect, bgImageName:String?,placeholder:String?) -> UITextField {
        
        let sTextField = UITextField.init()
        sTextField.frame = frame
        
        if let bgImageName = bgImageName {
            sTextField.background = UIImage.init(named: bgImageName)
        }
        if  let placeholder = placeholder {
            sTextField.placeholder = placeholder
        }
        return sTextField
    }
    
    
    class  func createTextFiledWithFrame(frame :CGRect, bgImageName:String ,placeholder:String ,cornerRadius:CGFloat? ) -> UITextField {
        let sTextField = createTextFiledWithFrame(frame: frame, bgImageName: bgImageName, placeholder: placeholder)
        
        if cornerRadius! > 0 {
            sTextField.clipsToBounds = true
            sTextField.layer.cornerRadius = cornerRadius!
            sTextField.layer.masksToBounds = true;
        }
        return sTextField
    }
    
    
}

// MARK: -
// MARK: - Tools Class
// MARK: -

///Make sure you use  "[weak self] (gesture) in" if you are using the keyword self inside the closure or there might be a memory leak
open class tapGestureBlock: UITapGestureRecognizer {
    private var tapAction: ((UITapGestureRecognizer) -> Void)?
    
    public override init(target: Any?, action: Selector?) {
        super.init(target: target, action: action)
    }
    public convenience init (
        tapCount: Int = 1,
        fingerCount: Int = 1,
        action: ((UITapGestureRecognizer) -> Void)?) {
        self.init()
        self.numberOfTapsRequired = tapCount
        #if os(iOS)
            self.numberOfTouchesRequired = fingerCount
        #endif
        self.tapAction = action
        self.addTarget(self, action: #selector(tapGestureBlock.didTap(_:)))
    }
    
    @objc open func didTap (_ tap: UITapGestureRecognizer) {
        tapAction? (tap)
    }
}


private var block_key: UInt8 = 0
typealias eventsBlock = (_ sender: Any) -> Void

extension UIControl {
    
    func addBlockForControlEvents(controlEvents:UIControlEvents?, eventsBlock:@escaping eventsBlock) {
        // 判断空
        guard controlEvents != nil else {
             return
        }
        // 初始化
        let target = UIControlBlockTarget.init(events: controlEvents!, action: eventsBlock)
        self.addTarget(target, action:#selector(UIControlBlockTarget.invoke(sender:)), for: controlEvents!)
        let targets : NSMutableArray = self.allUIControlBlockTargets()
        targets.add(target)
    }
    
    func allUIControlBlockTargets() -> NSMutableArray {
        
        var targets = (objc_getAssociatedObject(self, &block_key) as? NSMutableArray)
        if targets == nil {
            targets = NSMutableArray();
            objc_setAssociatedObject(self, &block_key, targets, .OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
        return targets!

    }
}

class UIControlBlockTarget: NSObject {
    
     var tapAction: eventsBlock?
     var events = UIControlEvents()
    
    override init() {
        super.init()
    }
    
    public convenience init(events:UIControlEvents,
                            action:@escaping eventsBlock) {
        self.init()
        tapAction = action
        self.events = events
    }
    @objc func invoke(sender :Any) {
        if tapAction != nil {
            tapAction!(sender)
        }
    }

}


